﻿using PSI.Helper;
using PSI.Models;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;

namespace PSI.Services {
    public class PermissionService : PSIBaseService {

        public bool HasPermission(string fid) {
            var user = UserService.GetLoginUser();
            if (user == null) {
                return false;
            }

            var sql = @"select count(p.fid)
                        from psi_user_role ur, psi_role_permission rp, psi_permission p
                        where ur.user_id = @userId and ur.role_id = rp.role_id 
                            and rp.permission_id = p.permission_id
                            and p.fid = @fid";
            var p = CreateDbParameters();
            p.AddWithValue("userId", user.Id);
            p.AddWithValue("fid", fid);

            var count = QueryCount(sql, p);

            return count > 0;
        }


        public List<Role> GetRole() {
            var result = new List<Role>();

            var sql = "select role_id, role_name from psi_role order by role_name";
            Query(sql, reader => {
                result.Add(new Role {
                    Id = reader.GetString(0),
                    Name = reader.GetString(1)
                });
            });

            return result;
        }

        public List<Permission> GetPermission(string roleId) {
            var result = new List<Permission>();
            var sql = @"select p.permission_id, p.permission_name
                        from psi_role_permission r, psi_permission p
                        where r.role_id = @roleId and r.permission_id = p.permission_id
                        order by p.permission_name";
            var p = CreateDbParameters();
            p.AddWithValue("roleId", roleId);
            Query(sql, p, reader => {
                result.Add(new Permission {
                    Id = reader.GetString(0),
                    Name = reader.GetString(1)
                });
            });

            return result;
        }

        public List<User> GetUsers(string roleId) {
            var result = new List<User>();
            var sql = @"
                    select u.user_id, u.login_name, u.user_name, o.org_full_name, u.enabled
                    from psi_user_role r, psi_user u, psi_org o
                    where r.role_id = @roleId and r.user_id = u.user_id and u.org_id = o.org_id
            ";
            var p = CreateDbParameters();
            p.AddWithValue("roleId", roleId);

            Query(sql, p, reader => {
                result.Add(new User {
                    Id = reader.GetString(0),
                    LoginName = reader.GetString(1),
                    Name = reader.GetString(2),
                    OrgFullName = reader.GetString(3),
                    Enabled = reader.GetInt32(4) == 1
                });
            });

            return result;
        }

        public List<Permission> SelectPermission(string idList) {
            var idArray = idList.Split(',').ToList();
            var sql = "select permission_id, permission_name from psi_permission order by permission_name";
            var data = new List<Permission>();
            Query(sql, reader => {
                data.Add(new Permission {
                    Id = reader.GetString(0),
                    Name = reader.GetString(1)
                });
            });

            var result = (from item in data
                          where idArray.IndexOf(item.Id) == -1
                          select item).ToList();

            return result;
        }

        public List<User> SelectUsers(string idList) {
            var data = new List<User>();
            var sql = @"
                    select u.user_id, u.login_name, u.user_name, o.org_full_name, u.enabled
                    from psi_user u, psi_org o
                    where u.org_id = o.org_id
            ";

            Query(sql, reader => {
                data.Add(new User {
                    Id = reader.GetString(0),
                    LoginName = reader.GetString(1),
                    Name = reader.GetString(2),
                    OrgFullName = reader.GetString(3),
                    Enabled = reader.GetInt32(4) == 1
                });
            });


            var idArray = idList.Split(',').ToList();

            var result = (from item in data
                          where idArray.IndexOf(item.Id) == -1
                          select item).ToList();

            return result;
        }

        public Result EditRole(string roleId, string roleName, string permissionIdList, string userIdList) {
            if (permissionIdList == null) {
                permissionIdList = string.Empty;
            }

            if (userIdList == null) {
                userIdList = string.Empty;
            }

            if (string.IsNullOrEmpty(roleId)) {
                // 新增角色
                var sql = "select count(*) from psi_role where role_name = @roleName";
                var p = CreateDbParameters();
                p.AddWithValue("roleName", roleName);
                var count = QueryCount(sql, p);

                if (count > 0) {
                    return new Result { Success = false, Messgae = "角色名称[" + roleName + "]已经存在" };
                }

                WithTransaction(() => {
                    roleId = IdGeneratorService.NewId();

                    sql = "insert into psi_role(role_id, role_name) values (@roleId, @roleName)";
                    p = CreateDbParameters();
                    p.AddWithValue("roleId", roleId);
                    p.AddWithValue("roleName", roleName);

                    Execute(sql, p);

                    sql = "insert into psi_role_permission(role_id, permission_id) values (@roleId, @permissionId)";
                    foreach (var permissionId in permissionIdList.Split(',')) {
                        p = CreateDbParameters();
                        p.AddWithValue("roleId", roleId);
                        p.AddWithValue("permissionId", permissionId);

                        Execute(sql, p);
                    }

                    sql = "insert into psi_user_role(role_id, user_id) values (@roleId, @userId)";
                    foreach (var userId in userIdList.Split(',')) {
                        p = CreateDbParameters();
                        p.AddWithValue("roleId", roleId);
                        p.AddWithValue("userId", userId);

                        Execute(sql, p);
                    }

                    new LogService().Log("新增角色: " + roleName);
                });

            } else {
                // 编辑角色
                var sql = "select count(*) from psi_role where role_name = @roleName and role_id <> @roleId";
                var p = CreateDbParameters();
                p.AddWithValue("roleName", roleName);
                p.AddWithValue("roleId", roleId);

                var count = QueryCount(sql, p);

                if (count > 0) {
                    return new Result { Success = false, Messgae = "角色名称[" + roleName + "]已经存在" };
                }

                WithTransaction(() => {
                    sql = "update psi_role set role_name = @roleName where role_id = @roleId";
                    p = CreateDbParameters();
                    p.AddWithValue("roleId", roleId);
                    p.AddWithValue("roleName", roleName);

                    Execute(sql, p);

                    sql = "delete from psi_role_permission where role_id = @roleId";
                    p = CreateDbParameters();
                    p.AddWithValue("roleId", roleId);
                    Execute(sql, p);

                    sql = "insert into psi_role_permission(role_id, permission_id) values (@roleId, @permissionId)";
                    foreach (var permissionId in permissionIdList.Split(',')) {
                        p = CreateDbParameters();
                        p.AddWithValue("roleId", roleId);
                        p.AddWithValue("permissionId", permissionId);

                        Execute(sql, p);
                    }

                    sql = "delete from psi_user_role where role_id = @roleId";
                    p = CreateDbParameters();
                    p.AddWithValue("roleId", roleId);
                    Execute(sql, p);

                    sql = "insert into psi_user_role(role_id, user_id) values (@roleId, @userId)";
                    foreach (var userId in userIdList.Split(',')) {
                        p = CreateDbParameters();
                        p.AddWithValue("roleId", roleId);
                        p.AddWithValue("userId", userId);

                        Execute(sql, p);
                    }


                    new LogService().Log("编辑角色: " + roleName + ", Id = " + roleId);
                });
            }

            return new Result { Success = true };
        }

        private Role GetRole(string roleId) {
            var role = new Role() { Id = roleId };
            var sql = "select role_name from psi_role where role_id = @roleId";
            var p = CreateDbParameters();
            p.AddWithValue("roleId", roleId);

            Query(sql, p, reader => {
                role.Name = reader.GetString(0);
            });

            return role;
        }

        public Result DeleteRole(string roleId) {
            WithTransaction(() => {
                var role = GetRole(roleId);

                var sql = @"
                    delete from psi_role where role_id = @roleId
                    delete from psi_role_permission where role_id = @roleId
                    delete from psi_user_role where role_id = @roleId
                ";

                var p = CreateDbParameters();
                p.AddWithValue("roleId", roleId);
                Execute(sql, p);

                new LogService().Log("删除角色: " + role.ToString());
            });

            return new Result { Success = true };
        }
    }
}